﻿#region License
/*

	Copyright (C) 2008 Oliver Charles, Daniel Hollander

	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program.  If not, see <http://www.gnu.org/licenses/>.
	
*/
#endregion

using System;
using System.Drawing;
using Moebius.Core;

namespace Moebius.Rendering
{
    /// <summary>
    /// Represents a rendering device capable of taking Moebius data, and displaying it in someway.
    /// </summary>
    /// <remarks>
    /// The <see cref="RenderingDevice"/> is the basis of Moebius' abstracted rendering system. This represents a
    /// device in some sense that will take engine input, transform it to API specific calls, and display the results on
    /// the users screen in some way. Moebius comes complete with a Direct3D9 implementation, that you can refer
    /// to if you wish to create your own <see cref="RenderingDevice"/>.
    /// </remarks>
    public abstract class RenderingDevice : Task
    {
        #region Properties

        private Size mScreenSize;
        private RenderingSubsystem mSubsystem;
        private Hud.HeadsUpDisplay mHud;
        private ResourceManager mResourceManager;
		private IntPtr mHandle;

        /// <summary>
        /// The subsystem that is assossciated with this <see cref="RenderingDevice"/>. The subsystem can be
        /// queried for all renderable components, so the device can render them.
        /// </summary>
        public RenderingSubsystem Subsystem
        {
            get { return mSubsystem; }
            protected set { mSubsystem = value; }
        }
        /// <summary>
        /// The heads up display attached to this rendering device. The huds up display allows clients to display
        /// various information on the screen, regardless of camera position.
        /// </summary>
        /// <seealso cref="Moebius.Hud"/>
        public Hud.HeadsUpDisplay Hud
        {
            get { return mHud; }
        }
        /// <summary>
        /// Gets the resource manager for this device, that is capable of creating <em>graphics specific</em>
        /// resources - such as meshes and textures.
        /// </summary>
        public ResourceManager ResourceManager
        {
            get { return mResourceManager; }
            protected set { mResourceManager = value; }
        }
        /// <summary>
        /// Gets the size of the screen that this rendering device is running on
        /// </summary>
        public Size ScreenSize
        {
            get { return mScreenSize; }
        }
		/// <summary>
		/// Gets a handle to this rendering device, at the API level.
		/// </summary>
		public IntPtr Handle
		{
			get { return mHandle; }
			protected set { mHandle = value; }
		}
		public virtual int ExtraSdlOptions
		{
			get { return 0; }
		}

        #endregion

        #region Initialize

        /// <summary>
        /// Initialize this rendering device with a specific window and graphics options.
        /// </summary>
        /// <param name="windowHandle">The window that this rendering device should display to.</param>
        /// <param name="screenSize">The size of the screen</param>
        /// <param name="graphicsOptions">Specific options to create this device.</param>
        /// <seealso cref="GraphicsOptions"/>
        public virtual void Initialize(IntPtr windowHandle, Size screenSize, GraphicsOptions graphicsOptions)
        {
            if (graphicsOptions == null) throw new ArgumentNullException("graphicsOptions");

			mScreenSize = screenSize;
            mHud = CreateHud();
        }

        #endregion
        #region Abstract Methods

        /// <summary>
        /// Renders the scene
        /// </summary>
        protected abstract void Render();

        /// <summary>
        /// Create a heads up display on this rendering device.
        /// </summary>
        /// <returns>A heads up display, bound to this device.</returns>
        protected abstract Hud.HeadsUpDisplay CreateHud();

        #endregion
        #region Register Resource Manager

        /// <summary>
        /// Register all resource managers of this rendering device, with a specific resource factory.
        /// </summary>
        /// <param name="factory">The <see cref="ResourceFactory"/> to register with.</param>
        public abstract void RegisterResourceManager(ResourceFactory factory);

        #endregion

        #region Kernel Implementation

        /// <summary>
        /// Executes the rendering device, by causing it to render
        /// </summary>
        /// <param name="elapsedTime">The amount of time elapsed since the last render</param>
        public override void Execute(double elapsedTime)
        {
            Render();
        }

        #endregion
    }
}